import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
import { PresignDto } from './dto/presign.dto';
import * as Minio from 'minio';
import { MINIO_CLIENT } from 'src/minio/minio.module';
import { UploadDto } from './dto/upload.dto';
import { Upload } from './entities/upload.entity';
import { InjectEntityManager } from '@nestjs/typeorm';
import { EntityManager } from 'typeorm';
import { PhotoListDto } from './dto/photoList.dto';
import * as dayjs from 'dayjs';
import { ALI_OSS_CLIENT } from 'src/oss/oss.module';
import * as AliOss from 'ali-oss';
import { ConfigService } from '@nestjs/config';
import { resolve } from 'path';
import { Request } from 'express';
@Injectable()
export class UploadService {
  @Inject(MINIO_CLIENT)
  private minioClient: Minio.Client;

  @Inject(ALI_OSS_CLIENT)
  private aliOssClient: AliOss.Client;

  @InjectEntityManager()
  private manager: EntityManager;

  @Inject(ConfigService)
  private configService: ConfigService;

  // presign file url
  async preSign(presignDto: PresignDto) {
    const types = ['senery', 'food', 'ereryday', 'art', 'photos'];
    const bucket = types[presignDto.type];
    try {
      const exists = await this.minioClient.bucketExists(bucket);
      if (!exists) {
        await this.minioClient.makeBucket(bucket);
      }
      return await this.minioClient.presignedPutObject(
        bucket,
        presignDto.name,
        3600,
      );
    } catch (error) {
      console.log(error);
      return error;
    }
  }

  // save uploadFile's url
  async uploadFile(uploadDto: UploadDto, userId:number, req:Request) {
    // c['senery', 'food', 'ereryday', 'art', '博客图片'];
    const url = new Upload();
    url.url = uploadDto.url;
    url.type = uploadDto.type;
    url.ip = req.ip;
    url.userId = userId
    try {
      await this.manager.save(Upload, url);
      return '上传成功';
    } catch (error) {
      console.log(error);
      return '上传失败';
    }
  }

  async getUploadList(photoListDto: PhotoListDto) {
    const skip = (photoListDto.pageNo - 1) * photoListDto.pageSize;
    try {
      const [result, total] = await this.manager.findAndCount(Upload, {
        skip: skip,
        take: photoListDto.pageSize,
        where: {
          type: photoListDto.type,
        },
      });
      return {
        list: result,
        total: total,
      };
    } catch (error) {
      console.log(error);
      return error;
    }
  }

  async ossSigned() {
    const date = new Date();
    // 时长加 1 天，作为签名的有限期
    date.setDate(date.getDate() + 1);
    const policy = {
      // 设置签名的有效期，格式为Unix时间戳
      expiration: date.toISOString(),
      conditions: [
        ['content-length-range', 0, 10485760], // 设置上传文件的大小限制 10M
      ],
    };
    // this.aliOssClient.dir = 'front-end'
    // this.aliOssClient.bucket =

    // 生成签名，策略等信息
    const formData = await this.aliOssClient.calculatePostSignature(policy);

    // 生成 bucket 域名，客户端将向此地址发送请求
    const location = await this.aliOssClient.getBucketLocation();
    const host = `https://${this.configService.get('oss_bucket')}.${location.location}.aliyuncs.com`;

    // 响应给客户端的签名和策略等信息
    return {
      expire: dayjs().add(1, 'days').unix().toString(),
      policy: formData.policy,
      signature: formData.Signature,
      accessId: formData.OSSAccessKeyId,
      host,
      dir: this.configService.get('oss_dir'),
    };
  }

  // 在oss删除图片
  async deleteImageByUrl(url: string): Promise<string> {
    try {
      const dir = url.split('aliyuncs.com/')?.[1] || '';
      const result = await this.aliOssClient.delete(dir);
      if (result.status === 204) {
        return '图片删除成功';
      } else {
        new HttpException(
          '图片删除失败，状态码:' + result.status,
          HttpStatus.BAD_REQUEST,
        );
      }
    } catch (error) {
      new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }

  // 批量删除
  async multiDelete(urls: string) {
    return new Promise(async(resolve, reject) => {
      try {
        const urlList = urls.split(',');
        urlList.map((url) => {
          return this.deleteImageByUrl(url);
        });
        await Promise.all(urlList)
          .then((res) => {
            if(urlList.length === res.length) {
              resolve(res)
            } else {
              throw new HttpException('有图片删除失败', HttpStatus.BAD_REQUEST);
            }
          })
          .catch((err) => reject(err));
      } catch (error) {
        throw new HttpException(error, HttpStatus.BAD_REQUEST);
      }
    });
  }

  //删除数据库图片url
  async deleteImageUrl(urls: string) {
    try {
      const urlList = urls.split(',');
      return this.manager
        .createQueryBuilder()
        .delete()
        .from(Upload)
        .where('url IN (:...urlList)', { urlList: urlList })
        .execute();
    } catch (error) {
      new HttpException(error, HttpStatus.BAD_REQUEST);
    }
  }
}
